package org.epsi.blokus.commun;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map.Entry;

/**
 * Message échangé entre le client et le server
 * @author julien.lafont
 */
public class Message implements Serializable {

    public enum TTypeMessage {
                                // Info : [ C = client, S = Serveur, M = maitre ]
                                // ack : acknowledge (accusé de réception)
        
        // Gestion des salons
        connexion_client,       // C->S : Connexion d'un client
        connexion_client_ack,   // S->C : Connexion acceptée
        creation_salon,         // C->S : Demande de création d'un salon
        creation_salon_ack,     // S->C : Création du salon réussie 
        creation_salon_err,     // S->C : Création du salon impossible
        entrer_salon,           // C->S : Entrer dans un salon 
        entrer_salon_ack,       // S->C : Entrée réussie
        entrer_salon_err,       // S->C : Entrée impossible
        sortir_salon,           // C->S : Sortir d'un un salon 
        sortir_salon_ack,       // S->C : Sortie d'un un salon
        sortir_salon_err,       // S->C : Sortie impossible 
        fermeture_salon,        // C->S : Fermer un salon
        fermeture_salon_ack,    // S->C : Fermer un salon ok
        deconnexion_client,     // C->S : Déconnexion d'un client
        deconnexion_client_ack, // S->C : Déconnexion ok
        ouverture_salon,        // S->C : Nouveau salon ouvert
        requete_nb_joueurs,     // C->S : Selecion d'un salon dans la liste
        reponse_nb_joueurs,     // S->C : Selecion d'un salon réussi
        salon_fermeture_prematuree,  // S->C : Le salon a fermé prématurément
        maj_liste_salons,       // S->C : Mise à jour de la liste des salons
        
        // Chat salon
        chat_salon_poster,     // C->S : Poster un message dans le chat du salon (String message)
        chat_salon_recevoir,   // S->C : Nouveau message reçu (String message, String source)

        // Démarage partie
        lancer_partie,          // M->S puis S->C : Lancement de la partie
        infos_adversaires,      // S->C : Indique au joueur les infos de son adversaire (String Pseudo, String image)
        nous_sommes_pret,       // C->S : Indique au serveur que les 2 joueurs sont prêts à jouer

        // Partie en cours
        a_toi_de_jouer,         // S->C : Indique au joueur que c'est à lui de jouer ( [int X, int Y : Dernier coup ] )
        en_attente,             // S->C : L'autre joueur est entrain de jouer
        poser_pion,             // C->S : Le joueur pose un pion
        timeout,                // C->S : Le client a dépassé son temps disponible

        // Fin du jeu
        gagnant,                // S->C : Joueur gagnant
        perdant,                // S->C : Joueur perdant

        // Chat in game
        chat_ingame_poster,     // C->S : Poster un message dans le chat ingame (String message)
        chat_ingame_recevoir,   // S->C : Nouveau message reçu (String message, String source)

        indefini               // Message invalide

    };

    private TTypeMessage type_message = TTypeMessage.indefini;
    private HashMap<String, Serializable> objects = new HashMap<String, Serializable>();


    /**
     * Crée un nouveau message avec le type spécifié
     * @param type_message
     */
    public Message( TTypeMessage type_message)
    {
        this.type_message = type_message;
    }

    /**
     * Crée un nouveau message sans type spécifié
     * @param type_message
     */
    public Message()
    {
        this.type_message = TTypeMessage.indefini;
    }

    /**
     * Définir le type du message
     * @param type
     * @return méthode fluide
     */
    public Message setTypeMessage(TTypeMessage type)
    {
        this.type_message = type;
        return this;
    }

    /**
     * Ajouter un objet serialisable au message (
     * @param key : Identifiant de l'objet
     * @param o : Objet serialisable
     * @return méthode fluide
     */
    public Message addObject(String key, Serializable o)
    {
        this.objects.put(key, o);
        return this;
    }




    /**
     * Retourne le type du message
     * @return type du message
     */
    public TTypeMessage getTypeMessage()
    {
        return this.type_message;
    }

    /**
     * Retourne l'objet défini par son identifiant
     * @param key
     * @return
     */
    public Serializable getObject(String key)
    {
        return this.objects.get(key);
    }


    /**
     * Affiche un debug complet de l'objet en cours
     * @return
     */
    public String debug()
    {
        StringBuffer buff = new StringBuffer();

        buff.append("Type : ").append(this.type_message.toString());
        for (Entry<String, Serializable> elem : objects.entrySet())
        {
            buff.append("\n - ").append(elem.getKey()).append(" = ").append(elem.getValue().toString());
        }
        return buff.toString();
    }
}
